# -*- coding: utf-8 -*-
# created on 2018/05/15
import copy
import math

from mathsolver.functions.shulie.ShuLie_Transform import (DengChaBiEqNormalization, DengChaBiExprNormalization,
                                                          DengChaBiJiChuAssume, ShuLieSnExprNormalization)
from mathsolver.functions.shulie.ShuLie_ZhouQiShuLie import sl_get_period
from mathsolver.functions.shulie.basic import *
from mathsolver.functions.shulie.Fundamental import *
from mathsolver.functions.base import *
from mathsolver.functions.shulie.base import ShuLieYiBanGetPoly, ShuLieDengChaBiSolveEqs, ShuLiePeriodValuesUpdate
from sympy import sympify
from sympy.abc import n


class ShuLieGetSeqPoly001(BaseFunction):
    """
    赋值法求数列的项或和
    eg. 已知数列\\{a_{n}\\}的前n项和为S_{n},且a_{2}a_{n} = S_{2} + S_{n}.求a_{1}的值.
    """
    def solver(self, *args):
        assert len(args) == 1
        seq = args[0].sympify()
        seq_xiangs = sl_xiangs(seq)
        flag = []
        for seq_xiang in seq_xiangs:
            new_item = sympify(seq_xiang)
            new_item_index = new_item.args[0]
            if sympify('n') not in new_item_index.free_symbols:
                flag.append(0)
            else:
                flag.append(1)
        assert sum(flag) == 0
        known = dict(self.known)
        assert 'Sequations' in known
        assert known['Sequations']
        seqs = known['Sequations']
        if known['inequations']:
            for ineq in known['inequations']:
                left, op, right = ineq
                new_ineq = [sympify(left), op, sympify(right)]
                if new_ineq not in seqs:
                    seqs.append(new_ineq)
        if known['equations']:
            for eq in known['equations']:
                if eq not in seqs:
                    seqs.append(eq)
        m_eqs = []
        m_eqs_eqs = 0
        m_eqs_symbols = 0
        n_eqs = []
        target_symbols = []
        for eq in seqs:
            expr = eq[0] - eq[1]
            expr_nxiangs = sl_xiangs001(expr)
            if expr_nxiangs:
                n_eqs.append(eq)
            else:
                expr = ShuLieSnExprNormalization().solver(BasePoly(expr), sympify('a_')).output[0].sympify()
                m_eqs.append([expr, S.Zero])
                m_eqs_eqs += 1
                expr_symbols = expr.free_symbols
                expr_symbols = list(expr_symbols)
                expr_xiangs = sl_xiangs(expr)
                if expr_xiangs:
                    for expr_Xiang in expr_xiangs:
                        expr_symbols.append(sympify(expr_Xiang))
                expr_symbols = set(expr_symbols)
                expr_symbols = list(expr_symbols)
                target_symbols.extend(expr_symbols)
                m_eqs_symbols += len(expr_symbols)
        assert n_eqs
        if len(n_eqs) == 1:
            eq = n_eqs[0]
            expr = eq[0] - eq[1]
            for i in range(1, 100):
                new_expr = expr.subs({n: i})
                new_expr = ShuLieSnExprNormalization().solver(BasePoly(new_expr), sympify('a_')).output[0].sympify()
                new_expr_symbols = new_expr.free_symbols
                new_expr_symbols = set(new_expr_symbols)
                new_expr_symbols = list(new_expr_symbols)
                for new_expr_symbol in new_expr_symbols:
                    if new_expr_symbol not in target_symbols:
                        target_symbols.append(new_expr_symbol)
                new_expr_xiangs = sl_xiangs(new_expr)
                for new_expr_xiang in new_expr_xiangs:
                    new_expr_xiang = sympify(new_expr_xiang)
                    if new_expr_xiang not in target_symbols:
                        target_symbols.append(new_expr_xiang)
                if (m_eqs_symbols == m_eqs_eqs) and (m_eqs_symbols * m_eqs_eqs != 0):
                    new_flag = []
                    for eq in m_eqs:
                        _expr = eq[0] - eq[1]
                        if str(_expr).find(str(seq)) >= 0:
                            new_flag.append(1)
                        else:
                            new_flag.append(0)
                    if sum(new_flag) > 0:
                        break
                    else:
                        m_eqs.append([new_expr, S.Zero])
                        m_eqs_eqs += 1
                        m_eqs_symbols = len(target_symbols)
                else:
                    m_eqs_symbols = len(target_symbols)
                    m_eqs_eqs += 1
                    m_eqs.append([new_expr, S.Zero])
        assert len(m_eqs) == len(m_eqs_symbols)
        self.steps.append(["", "依题意, 得"])
        if len(m_eqs) == 1:
            if len(m_eqs[0]) == 2:
                self.steps.append(["", "%s" % BaseEq(m_eqs[0]).printing()])
            else:
                self.steps.append(["", "%s" % BaseIneq(m_eqs[0]).printing()])
        else:
            self.steps.append(["", "%s" % BaseIneqs(m_eqs).printing()])
        solutions = MathematicaSolve().solver(BaseIneqs(m_eqs)).output[0]
        self.steps.append(["", "解得: %s" % solutions.printing()])
        seq_values = sl_solutuons_subs(solutions, seq)
        assert seq_values
        seq_flag = []
        for seq_value in seq_values:
            if str(seq) == str(seq_value):
                seq_flag.append(1)
            else:
                seq_flag.append(0)
        assert sum(seq_flag) == 0
        self.steps.append(["", "∴%s" % "或".join(["%s = %s" % (new_latex(seq), new_latex(v)) for v in seq_values])])
        self.output.append(BaseNumbers(seq_values))
        return self


class ShuLieGetSeqPoly002(BaseFunction):
    """
    1.求数列的项或和
    2.单数列
    3.等差，等比数列型
    4.new_otherSeqs空
    eg. 等差数列{a_{n}}中,a_{5}+a_{7}=16,a_{3}=4,则a_{9}=.
        设数列{a_{n}}是首项为1,公比为-2的等比数列,则a_{1}+|a_{2}|+a_{3}+|a_{4}|=.
    """
    def solver(self, *args):
        assert len(args) == 1
        known = dict(self.known)
        seqs = known.get('Sequations', [])
        if seqs:
            if known['inequations']:
                for ineq in known['inequations']:
                    left, op, right = ineq
                    new_ineq = [sympify(left), op, sympify(right)]
                    if new_ineq not in seqs:
                        seqs.append(new_ineq)
            if known['equations']:
                for eq in known['equations']:
                    if eq not in seqs:
                        seqs.append(eq)
            new_seqs, new_other_seqs = sl_seqs_other_seqs(known, seqs)
            assert not new_other_seqs
            assert new_seqs
            sls, sl_flag = sl_shulies_flag(known, new_seqs)
            assert sum(sl_flag) == 0
            sls = [self.known[item] for item in self.known if isinstance(self.known[item], BaseSequence)]
            stepsolver = DengChaBiJiChuAssume(known=self.known).solver(sls)
            self.steps += stepsolver.steps
            self.label.update(stepsolver.label)
            stepsolver = DengChaBiEqNormalization(known=self.known).solver(seqs)
            self.steps += stepsolver.steps
            self.label.update(stepsolver.label)
            stepsolver = MathematicaSolve().solver(stepsolver.output[0], [])
            self.steps.append(["", "解得: %s" % (stepsolver.output[0].printing())])
            solutions = stepsolver.output[0]
            target = args[0].sympify()
            stepsolver = DengChaBiExprNormalization(known).solver(BasePoly(target))
            self.steps += stepsolver.steps
            self.label.update(stepsolver.label)
            new_target = stepsolver.output[0].sympify()
            if solutions.sympify():
                if type(solutions.sympify()) == bool:
                    target_values = [new_target]
                else:
                    target_values = sl_solutuons_subs(solutions, new_target)
            else:
                target_values = [new_target]
            self.steps.append(["", "∴%s" % "或".join(["%s = %s" % (new_latex(args[0].sympify()), new_latex(v)) for v in target_values])])
            self.output.append(BaseNumbers(target_values))
        else:
            # 设数列{a_{n}}是首项为1,公比为-2的等比数列,则a_{1}+|a_{2}|+a_{3}+|a_{4}|=.
            sls = [self.known[item] for item in self.known if isinstance(self.known[item], BaseSequence)]
            assert sls
            stepsolver = DengChaBiJiChuAssume(known=self.known).solver(sls)
            self.steps += stepsolver.steps
            self.label.update(stepsolver.label)
            target = args[0].sympify()
            if not sl_xiangs(target):
                if len(sls) == 1 and sls[0].an:
                    sl = sls[0]
                    an = sl.an[0]
                    if sl.type == 'DengCha':
                        d_value = an.subs({sl.nName: 2}) - an.subs({sl.nName: 1})
                        target = sl_solutuons_subs(BaseSymbolValue({sl.dValue: d_value}), target)
                        self.steps.append(["", "∴%s" % "或".join(["%s = %s" % (new_latex(args[0].sympify()), new_latex(v)) for v in target])])
                        self.output.append(BaseNumbers(target))
            else:
                stepsolver = DengChaBiExprNormalization(known).solver(BasePoly(target))
                self.steps += stepsolver.steps
                self.label.update(stepsolver.label)
                new_target = stepsolver.output[0].sympify()
                target_values = [new_target]
                self.output.append(BaseNumbers(target_values))
        return self


class ShuLieGetSeqPoly003(BaseFunction):
    """
    设等差数列{a_{n}}的公差为d,前n项和为S_{n},等比数列{b_{n}}的公比为q.已知b_{1}=a_{1},b_{2}=2,q=d,S_{10}=100.当d>1时,
    记c_{n}=\\frac{a_{n}}{b_{n}},求数列{c_{n}}的前n项和为T_{n}.
    1.求数列的项或和
    2.单数列
    3.等差，等比数列型
    4.new_otherSeqs非空
    """
    def solver(self, *args):
        assert len(args) == 1
        known = dict(self.known)
        assert 'Sequations' in known
        assert known['Sequations']
        seqs = known['Sequations']
        if known['inequations']:
            for ineq in known['inequations']:
                left, op, right = ineq
                new_ineq = [sympify(left), op, sympify(right)]
                if new_ineq not in seqs:
                    seqs.append(new_ineq)
        if known['equations']:
            for eq in known['equations']:
                if eq not in seqs:
                    seqs.append(eq)
        new_seqs, new_other_seqs = sl_seqs_other_seqs(known, seqs)
        assert new_other_seqs
        assert new_seqs
        sls, sl_flag = sl_shulies_flag(known, new_seqs)
        assert sum(sl_flag) == 0
        seq = args[0].sympify()
        seq_values = sl_solve_an(new_other_seqs, seq)
        assert len(seq_values) == 1
        new_seq = seq_values[0]
        known['Sequations'] = new_seqs
        stepsolver = ShuLieGetSeqPoly002(known).solver(BaseSeqPoly(new_seq))
        self.steps += stepsolver.steps
        self.label.update(stepsolver.label)
        new_seq_values = stepsolver.output[0].sympify()
        self.output.append(BaseNumbers(new_seq_values))
        return self


class ShuLieGetSeqPoly004(BaseFunction):
    """
    数列\\{a_{n}\\}的首项为3,\\{b_{n}\\}为等差数列且b_{n}=a_{n+1}-a_{n},若b_{3}=-2,b_{10}=12,则b_{8}=()
    1.求数列的通项
    2.双数列: 一个数列为等差，等比类型; 另外一个为一般数列
    3.所求数列为等差，等比数列
    """
    def solver(self, *args):
        assert len(args) == 1
        known = dict(self.known)
        assert 'Sequations' in known
        assert known['Sequations']
        seqs = known['Sequations']
        new_seqs, new_other_seqs = sl_seqs_other_seqs(known, seqs)
        assert not new_other_seqs
        assert new_seqs
        seq = args[0].sympify()
        sls, sl_flag = sl_shulies_flag(known, new_seqs)
        assert sum(sl_flag) > 0
        assert len(sls) == 2
        seq_names = sl_shulie_name(seq)
        assert len(seq_names) == 1
        seq_name = seq_names[0]
        seq_shulie = self.search(str(seq_name))
        seq_shulie_type = seq_shulie.type
        assert (seq_shulie_type == str("DengCha") or seq_shulie_type == str("DengBi"))
        ditui_eqs, nditui_eqs = sl_ditui_or_not_ditui(seqs)
        condition_eqs = []
        condition_eqs_symbols = []
        for NDiTui_Eq in nditui_eqs:
            if len(NDiTui_Eq) == 2:
                expr = NDiTui_Eq[0] - NDiTui_Eq[1]
            else:
                expr = NDiTui_Eq[0] - NDiTui_Eq[2]
            expr = ShuLieSnExprNormalization().solver(BasePoly(expr), sympify('a_')).output[0].sympify()
            expr_xiangs = sl_xiangs(expr)
            for expr_xiang in expr_xiangs:
                condition_eqs_symbols.append(expr_xiang)
            condition_eqs.append(NDiTui_Eq)
        condition_eqs_num = len(condition_eqs)
        condition_eqs_symbols = set(condition_eqs_symbols)
        condition_eqs_symbols = list(condition_eqs_symbols)
        for eq in ditui_eqs:
            if len(eq) == 2:
                expr = eq[0] - eq[1]
            else:
                expr = eq[0] - eq[2]
            for i in range(1, 5):
                new_expr = expr.subs({seq_shulie.nName: i})
                new_expr = ShuLieSnExprNormalization().solver(BasePoly(new_expr), sympify('a_')).output[0].sympify()
                if len(condition_eqs_symbols) == condition_eqs_num and condition_eqs_num != 0:
                    break
                else:
                    if len(eq) == 2:
                        condition_eqs.append([new_expr, S.Zero])
                    else:
                        condition_eqs.append([new_expr, eq[1], S.Zero])
                    condition_eqs_num += 1
                    expr_xiangs = sl_xiangs(new_expr)
                    for expr_xiang in expr_xiangs:
                        condition_eqs_symbols.append(expr_xiang)
                    condition_eqs_symbols = set(condition_eqs_symbols)
                    condition_eqs_symbols = list(condition_eqs_symbols)
        sls = [self.known[item] for item in self.known if isinstance(self.known[item], (BaseShuLieDengCha, BaseShuLieDengBi))]
        stepsolver = DengChaBiJiChuAssume(known=self.known).solver(sls)
        self.steps += stepsolver.steps
        self.label.update(stepsolver.label)
        stepsolver1 = ShuLieDengChaBiSolveEqs(known).solver(BaseIneqs(condition_eqs), [])
        self.steps += stepsolver1.steps
        self.label.update(stepsolver1.label)
        solutions = stepsolver1.output[0]
        stepsolver2 = DengChaBiExprNormalization(known).solver(BasePoly(seq))
        self.steps += stepsolver2.steps
        new_seq = stepsolver2.output[0].sympify()
        seq_values = sl_solutuons_subs(solutions, new_seq)
        self.steps.append(
            ["", "∴%s" % "或".join(["%s = %s" % (new_latex(args[0].sympify()), new_latex(v)) for v in seq_values])])
        self.output.append(BaseNumbers(seq_values))
        return self


class ShuLieGetSeqPoly005(BaseFunction):
    """
    已知数列{a_{n}}的前n项和为S_{n},a_{1}=1,S_{n}=2a_{n+1},则S_{n}=()
    1.求数列的通项或和
    2.单数列
    3.一般数列型
    4.new_otherSeqs空
    """
    def solver(self, *args):
        assert len(args) == 1
        known = copy.deepcopy(self.known)
        assert 'Sequations' in known
        assert known['Sequations']
        seqs = known['Sequations']
        if known['inequations']:
            for ineq in known['inequations']:
                left, op, right = ineq
                new_ineq = [sympify(left), op, sympify(right)]
                if new_ineq not in seqs:
                    seqs.append(new_ineq)
        if known['equations']:
            for eq in known['equations']:
                if eq not in seqs:
                    seqs.append(eq)
        new_seqs, new_other_seqs = sl_seqs_other_seqs(known, seqs)
        assert not new_other_seqs
        assert new_seqs
        sls, sl_flag = sl_shulies_flag(known, new_seqs)
        assert sum(sl_flag) > 0
        seq = args[0].sympify()
        stepsolver = ShuLieYiBanGetPoly(known=known).solver(BaseSeqPoly(seq), BaseIneqs(new_seqs))
        assert stepsolver.output[0].sympify()
        self.steps += stepsolver.steps
        self.label.update(stepsolver.label)
        self.output.append(stepsolver.output[0])
        return self


class ShuLieGetSeqPoly006(BaseFunction):
    """
    已知数列{a_{n}}的前n项和{S_{n}}=\\frac{{{n^2}+n}}{2}.设b_{n}=2^{a_{n}}+{(-1)^n}{a_{n}},求数列{b_{n}}的前2n项和.
    1.求数列的通项
    2.单数列
    3.一般数列型
    4.new_otherSeqs非空
    """
    def solver(self, *args):
        assert len(args) == 1
        known = dict(self.known)
        assert 'Sequations' in known
        assert known['Sequations']
        seqs = known['Sequations']
        if known['inequations']:
            for ineq in known['inequations']:
                left, op, right = ineq
                new_ineq = [sympify(left), op, sympify(right)]
                if new_ineq not in seqs:
                    seqs.append(new_ineq)
        if known['equations']:
            for eq in known['equations']:
                if eq not in seqs:
                    seqs.append(eq)
        new_seqs, new_other_seqs = sl_seqs_other_seqs(known, seqs)
        assert new_other_seqs
        assert new_seqs
        sls, sl_flag = sl_shulies_flag(known, new_seqs)
        assert sum(sl_flag) > 0
        seq = args[0].sympify()
        seq_xiangs = sl_xiangs(seq)
        assert len(seq_xiangs) == 1
        seq_xiang = sympify(seq_xiangs[0])
        seq_xiang_values = sl_solve_an(new_other_seqs, seq_xiang)
        assert len(seq_xiang_values) == 1
        new_seq_xiang = seq_xiang_values[0]
        known['Sequations'] = new_seqs
        stepsolver = ShuLieGetSeqPoly005(known).solver(BaseSeqPoly(new_seq_xiang))
        self.steps += stepsolver.steps
        self.label.update(stepsolver.label)
        new_seq_xiang_values = stepsolver.output[0].sympify()
        new_seq_values = []
        for new_seq_xiang_value in new_seq_xiang_values:
            new_seq_value = seq.subs({seq_xiang: new_seq_xiang_value})
            new_seq_values.append(new_seq_value)
        self.output.append(BaseNumbers(new_seq_values))
        return self


class ShuLieGetSeqPoly007(BaseFunction):
    """
    已知数列的通项a_{n}=-5n+2,则其前n项和S_{n}=.
    1.一般数列
    2.无Sequations
    3.已知通项公式
    """
    def solver(self, *args):
        assert len(args) == 1
        known = dict(self.known)
        assert 'Sequations' not in known
        seq = args[0].sympify()
        seq_xiangs = sl_xiangs(seq)
        sls = []
        for seq_xiang in seq_xiangs:
            new_item = sympify(seq_xiang)
            new_item_name = new_item.func
            sl = self.search(str(new_item_name))
            if sl is not None:
                sls.append(sl)
        sls = set(sls)
        sls = list(sls)
        if not sls:
            sls = [self.known[item] for item in self.known if isinstance(self.known[item], BaseSequence)]
        assert len(sls) == 1
        sl = sls[0]
        a_name = sl.aName
        n_name = sl.nName
        tongxiangs = sl.an
        assert tongxiangs
        seq_values = []
        for TongXiang in tongxiangs:
            new_seq = seq
            for seq_xiang in seq_xiangs:
                new_xiang = sympify(seq_xiang)
                new_xiang_name = new_xiang.func
                new_xiang_index = new_xiang.args[0]
                p = r'[a-z]_'
                m = re.findall(p, str(new_xiang_name))
                if m:
                    new_xiang_value = TongXiang.subs({n_name: new_xiang_index})
                else:
                    from mathsolver.functions.shulie.QianNXiangHe import ShuLieQiuHe
                    stepsolver = ShuLieQiuHe().solver([sympify(a_name)(n_name), TongXiang], 1, new_xiang_index)
                    self.steps += stepsolver.steps
                    self.label.update(stepsolver.label)
                    new_xiang_value = stepsolver.output[0].sympify()[0]
                new_seq = new_seq.subs({new_xiang: new_xiang_value})
            new_seq = MathematicaSimplify().solver(BasePoly(new_seq)).output[0].sympify()
            seq_values.append(new_seq)
        seq_values = set(seq_values)
        seq_values = list(seq_values)
        self.steps.append(["", "∴%s" % "或".join(["%s = %s" % (new_latex(seq), new_latex(v)) for v in seq_values])])
        self.output.append(BaseNumbers(seq_values))
        return self


class ShuLieGetSeqPoly008(BaseFunction):
    """
    数列\\{a_{n}\\}的首项为3,\\{b_{n}\\}为等差数列且b_{n}=a_{n+1}-a_{n},若b_{3}=-2,b_{10}=12,则a_{8}=()
    1.求数列的通项
    2.双数列: 一个数列为等差，等比类型; 另外一个为一般数列
    3.所求数列为一般数列
    """
    def solver(self, *args):
        assert len(args) == 1
        known = dict(self.known)
        assert 'Sequations' in known
        seqs = known['Sequations']
        assert seqs
        new_seqs, new_other_seqs = sl_seqs_other_seqs(known, seqs)
        assert not new_other_seqs
        assert new_seqs
        sls, sl_flag = sl_shulies_flag(known, new_seqs)
        assert sum(sl_flag) > 0
        assert len(sls) == 2
        seq = args[0].sympify()
        otherseqs = []
        for eq in new_seqs:
            xiangs = sl_xiangs001(eq[0] - eq[1])
            if xiangs:
                for xiang in xiangs:
                    xiang = sympify(xiang)
                    xiang_name = xiang.func
                    if str(xiang_name) != str(seq.func):
                        otherseqs.append(xiang_name(sympify('n')))
        otherseqs = set(otherseqs)
        otherseqs = list(otherseqs)
        assert len(otherseqs) == 1
        otherseq = otherseqs[0]
        otherseq_name = otherseq.func
        otherseq_sl = self.search(str(otherseq_name))
        otherseq_sl_type = otherseq_sl.type
        assert (otherseq_sl_type == "DengCha" or otherseq_sl_type == "DengBi")
        stepsolver = ShuLieGetSeqPoly004(known).solver(BasePoly(otherseq))
        self.steps += stepsolver.steps
        self.label.update(stepsolver.label)
        tongxiangs = stepsolver.output[0].sympify()
        assert len(tongxiangs) == 1
        tongxiang = tongxiangs[0]
        new_known = copy.deepcopy(known)
        update_seqs = []
        for eq in new_seqs:
            expr = eq[0] - eq[1]
            expr = simplify(expr)
            xiangs = sl_xiangs(expr)
            if xiangs:
                for xiang in xiangs:
                    xiang = sympify(xiang)
                    xiang_name = xiang.func
                    if str(xiang_name) == str(otherseq.func):
                        xiang_index = xiang.args[0]
                        xiang_value = tongxiang.subs({sympify('n'): xiang_index})
                        expr = expr.subs({xiang: xiang_value})
                        expr = simplify(expr)
            if expr != 0:
                update_seqs.append([expr, S.Zero])
        new_known['Sequations'] = update_seqs
        del new_known[otherseq_sl.name]
        stepsolver = ShuLieGetSeqPoly005(new_known).solver(BasePoly(seq))
        self.steps += stepsolver.steps
        self.label.update(stepsolver.label)
        self.output.append(stepsolver.output[0])
        return self


class ShuLieGetSeqPoly009(BaseFunction):
    """
    设数列{a_{n}}满足a_{1}=0,a_{n+1}=\\frac{1}{2-a_{n}}.设{b}_{n}=\\frac{1-\\sqrt{{a}_{n+1}}}{\\sqrt{n}},数列\\{b_{n}\\}的前n项和为S_{n},求S_{n}.
    1.求数列的项或和
    2.双数列:两个一般数列
    """
    def solver(self, *args):
        assert len(args) == 1
        known = dict(self.known)
        assert 'Sequations' in known
        assert known['Sequations']
        seqs = known['Sequations']
        new_seqs, new_other_seqs = sl_seqs_other_seqs(known, seqs)
        assert not new_other_seqs
        assert new_seqs
        seq = args[0].sympify()
        sls, sl_flag = sl_shulies_flag(known, new_seqs)
        assert sum(sl_flag) > 0
        assert len(sls) == 2
        sl1, sl2 = sls
        assert sl1.type == "ShuLie" and sl2.type == "ShuLie"
        sl1.get_init()
        sl2.get_init()
        seq_name = seq.func
        if str(seq_name) == str(sl1.aName) or str(seq_name) == str(sl1.sName):
            target_sl = sl1
            other_sl = sl2
        else:
            target_sl = sl2
            other_sl = sl1
        other_sl_eqs = sl_get_other_shulie_eqs(other_sl, seqs)
        assert other_sl_eqs
        target_sl_eqs = sl_get_target_shulie_eqs(target_sl, seqs)
        assert target_sl_eqs
        other_sl_known = dict(known)
        target_sl_name = target_sl.name
        other_sl_name = other_sl.name
        other_sl_aname = other_sl.aName
        other_sl_sname = other_sl.sName
        other_sl_nname = other_sl.nName
        del other_sl_known[target_sl_name]
        del other_sl_known['Sequations']
        other_sl_known['Sequations'] = other_sl_eqs
        other_seqpoly_names = []
        for eq in target_sl_eqs:
            if len(eq) == 2:
                expr = eq[0] - eq[1]
            else:
                expr = eq[0] - eq[2]
            expr_xiangs = sl_xiangs(expr)
            for expr_xiang in expr_xiangs:
                new_item = sympify(expr_xiang)
                new_item_name = new_item.func
                if str(new_item_name) == str(other_sl_aname) or str(new_item_name) == str(other_sl_sname):
                    other_seqpoly_names.append(str(new_item_name))
        other_seqpoly_names = set(other_seqpoly_names)
        other_seqpoly_names = list(other_seqpoly_names)
        if str(other_sl_sname) in other_seqpoly_names:
            cls = [ShuLieGetSeqPoly001, ShuLieGetSeqPoly002, ShuLieGetSeqPoly005]
            r = None
            for cl in cls:
                try:
                    r = cl(known=other_sl_known, verbose=True).solver(
                        BaseSeqPoly(other_sl_aname(other_sl_nname)))
                    break
                except Exception:
                    pass
            assert r.output[0].sympify()
            self.steps += r.steps
            self.label.update(r.label)
            other_sl_tongxiangs = r.output[0].sympify()
            assert len(other_sl_tongxiangs) == 1
            other_sl_tongxiang = other_sl_tongxiangs[0]
            from mathsolver.functions.shulie.QianNXiangHe import ShuLieQiuHe
            stepsolver = ShuLieQiuHe().solver([other_sl_aname(other_sl_nname), other_sl_tongxiang], n)
            self.steps += stepsolver.steps
            self.label.update(stepsolver.label)
            other_sl_sns = stepsolver.output[0].sympify()
            assert len(other_sl_sns) == 1
            other_sl_sn = other_sl_sns[0]
            for index, eq in enumerate(target_sl_eqs):
                if len(eq) == 2:
                    expr = eq[0] - eq[1]
                else:
                    expr = eq[0] - eq[2]
                expr_xiangs = sl_xiangs(expr)
                for expr_xiang in expr_xiangs:
                    new_item = sympify(expr_xiang)
                    new_item_name = new_item.func
                    new_item_index = new_item.args[0]
                    if str(new_item_name) == str(other_sl_aname):
                        new_item_value = other_sl_tongxiang.subs({n: new_item_index})
                        expr = expr.subs({new_item: new_item_value})
                    elif str(new_item_name) == str(other_sl_sname):
                        new_item_value = other_sl_sn.subs({n: new_item_index})
                        expr = expr.subs({new_item: new_item_value})
                expr = expr.expand().simplify()
                if len(eq) == 2:
                    target_sl_eqs[index] = [expr, S.Zero]
                else:
                    target_sl_eqs[index] = [expr, eq[1], S.Zero]
        else:
            cls = [ShuLieGetSeqPoly001, ShuLieGetSeqPoly005]
            r = None
            for cl in cls:
                new_other_sl_known = copy.deepcopy(other_sl_known)
                try:
                    r = cl(known=new_other_sl_known, verbose=True).solver(BaseSeqPoly(sympify(other_sl_aname)(other_sl_nname)))
                    break
                except Exception:
                    pass
            assert r.output[0].sympify()
            self.steps += r.steps
            self.label.update(r.label)
            other_sl_tongxiangs = r.output[0].sympify()
            assert len(other_sl_tongxiangs) == 1
            other_sl_tongxiang = other_sl_tongxiangs[0]
            for index, eq in enumerate(target_sl_eqs):
                if len(eq) == 2:
                    expr = eq[0] - eq[1]
                else:
                    expr = eq[0] - eq[2]
                expr_xiangs = sl_xiangs(expr)
                for expr_xiang in expr_xiangs:
                    new_item = sympify(expr_xiang)
                    new_item_name = new_item.func
                    new_item_index = new_item.args[0]
                    if str(new_item_name) == str(other_sl_aname):
                        new_item_value = other_sl_tongxiang.subs({n: new_item_index})
                        expr = expr.subs({new_item: new_item_value})
                expr = expr.expand().simplify()
                if len(eq) == 2:
                    target_sl_eqs[index] = [expr, S.Zero]
                else:
                    target_sl_eqs[index] = [expr, eq[1], S.Zero]
        target_sl_known = dict(known)
        del target_sl_known[other_sl_name]
        del target_sl_known['Sequations']
        target_sl_known['Sequations'] = target_sl_eqs
        cls = [ShuLieGetSeqPoly001, ShuLieGetSeqPoly002, ShuLieGetSeqPoly005]
        r = None
        for cl in cls:
            try:
                r = cl(known=target_sl_known, verbose=True).solver(BaseSeqPoly(seq))
                break
            except Exception:
                pass
        assert r.output[0].sympify()
        self.steps += r.steps
        self.label.update(r.label)
        self.output.append(r.output[0])
        return self


class ShuLieGetSeqPoly010(BaseFunction):
    """
    已知等比数列{a_{n}}中,a_{1}=\\frac{1}{3},公比q=\\frac{1}{3}.设b_{n}=log_{3}a_{1}+log_{3}a_{2}+…+log_{3}a_{n},求\\frac{1}{b_{n}}.
    1. 求数列的项或和
    2. 单数列
    4. b_{n}=log_{3}a_{1}+log_{3}a_{2}+…+log_{3}a_{n}
    """
    def solver(self, *args):
        assert len(args) == 1
        known = self.known
        assert 'Sequations' in known
        assert known['Sequations']
        seqs = known['Sequations']
        new_seqs, new_other_seqs = sl_seqs_other_seqs(known, seqs)
        assert not new_other_seqs
        assert new_seqs
        assert 'InfSequations' in known
        assert known['InfSequations']
        inf_seqs = known['InfSequations']
        assert len(inf_seqs) == 1
        inf_seq = inf_seqs[0]
        left, right = inf_seq
        new_known = dict(known)
        del new_known['InfSequations']
        seq = args[0].sympify()
        if isinstance(left, str):
            raise Exception("to do")
        else:
            left_shulie_name = sl_shulie_name(left)
            seq_shulie_name = sl_shulie_name(seq)
            assert len(left_shulie_name) == len(seq_shulie_name)
            assert str(left_shulie_name[0]) == str(seq_shulie_name[0])
            from mathsolver.functions.shulie.ShuLie_getInfSums import ShuLieGetInfSums
            stepsolver = ShuLieGetInfSums(new_known).solver(BaseSeqInfPoly(right))
            self.steps += stepsolver.steps
            self.label.update(stepsolver.label)
            tongxiangs = stepsolver.output[0].sympify()
            seq_values = []
            for TongXiang in tongxiangs:
                new_seq = seq
                new_seq_xiangs = sl_xiangs(new_seq)
                for new_seq_xiang in new_seq_xiangs:
                    new_item = sympify(new_seq_xiang)
                    new_item_index = new_item.args[0]
                    new_item_value = TongXiang.subs({n: new_item_index})
                    new_seq = new_seq.subs({new_item: new_item_value})
                new_seq = new_seq.expand().simplify()
                seq_values.append(new_seq)
            seq_values = set(seq_values)
            seq_values = list(seq_values)
            self.steps.append(["", "%s" % "或".join(["%s = %s" % (new_latex(seq), new_latex(v)) for v in seq_values])])
            self.output.append(BaseNumbers(seq_values))
        return self


class ShuLieGetSeqPoly011(BaseFunction):
    """
    数列{a_{n}}满足a_{n+1}=\\frac{1}{1-{a}_{n}},a_{8}=2,则a_{1}=().
    1.迭代求解
    2.递推式是:a_(n+1), a_(n)的关系
    3.周期数列
    """
    def solver(self, *args):
        assert len(args) == 1
        known = dict(self.known)
        assert 'Sequations' in known
        assert known['Sequations']
        seqs = known['Sequations']
        if known['inequations']:
            for ineq in known['inequations']:
                left, op, right = ineq
                new_ineq = [sympify(left), op, sympify(right)]
                if new_ineq not in seqs:
                    seqs.append(new_ineq)
        if known['equations']:
            for eq in known['equations']:
                if eq not in seqs:
                    seqs.append(eq)
        new_seqs, new_other_seqs = sl_seqs_other_seqs(known, seqs)
        assert not new_other_seqs
        assert new_seqs
        sls, sl_flag = sl_shulies_flag(known, new_seqs)
        assert len(sls) == 1
        sl = sls[0]
        sl_type = sl.type
        assert sl_type == "ShuLie"
        sl.eqs_update(new_seqs)
        sl.get_shouxiang()
        sl.get_dituigongshi()
        sl.get_xiangs()
        sl.get_nineqs()
        dituigongshis = sl.DiTuiGongShi_Eqs
        assert len(dituigongshis) == 1
        dituigongshi = dituigongshis[0]
        seq_answer, seq_period, seq_values = sl_get_period(dituigongshi)
        assert seq_answer
        xiangs = sl.Xiangs_Eqs
        assert xiangs
        stepsovler = ShuLiePeriodValuesUpdate().solver(sl, seq_period, seq_values)
        self.steps += stepsovler.steps
        self.label.update(stepsovler.label)
        new_seq_values = stepsovler.output[0].sympify()
        seq = args[0].sympify()
        seq_xiangs = sl_xiangs(seq)
        new_seq = seq
        for seq_xiang in seq_xiangs:
            new_item = sympify(seq_xiang)
            new_item_name = new_item.func
            new_item_index = new_item.args[0]
            if str(new_item_name) == str(sl.aName):
                t = sympify('t')
                ineqs = [[new_item_index - seq_period * t, '>=', 1],
                         [new_item_index - seq_period * t, '<=', seq_period]]
                solutions = MathematicaSolve().solver(BaseIneqs(ineqs)).output[0].sympify()
                t_value = solutions[t]
                tleft, tright, tlopen, tropen = t_value.args
                tleft = int(math.ceil(tleft))
                tright = int(tright)
                t_value = range(tleft, tright + 1)
                assert len(t_value) == 1
                t_value = t_value[0]
                new_item_value = new_seq_values[t_value]
                new_seq = new_seq.subs({new_item: new_item_value})
        new_seq = MathematicaSimplify().solver(BasePoly(new_seq)).output[0].sympify()
        self.steps.append(["", "依题意, 得"])
        self.steps.append(["", "%s = %s" % (new_latex(seq), new_latex(new_seq))])
        self.output.append(BaseNumber(new_seq))
        return self


class ShuLieGetSeqPoly(BaseFunction):
    CLS = [ShuLieGetSeqPoly001, ShuLieGetSeqPoly002, ShuLieGetSeqPoly003, ShuLieGetSeqPoly004, ShuLieGetSeqPoly005,
           ShuLieGetSeqPoly006,
           ShuLieGetSeqPoly007, ShuLieGetSeqPoly008, ShuLieGetSeqPoly009, ShuLieGetSeqPoly010, ShuLieGetSeqPoly011]

    def solver(self, *args):
        r = None
        for cl in ShuLieGetSeqPoly.CLS:
            new_known = dict(self.known)
            try:
                r = cl(known=new_known, verbose=True).solver(*args)
                break
            except Exception:
                pass
        if not r:
            print("ShuLieGetSeqPoly failed")
        return r


class ShuLieGetSeqPolys(BaseFunction):
    def solver(self, *args):
        seqs = args[0].sympify()
        known = self.known
        for seq in seqs:
            new_known = dict(known)
            stepsolver = ShuLieGetSeqPoly(new_known).solver(BaseSeqPoly(seq))
            self.steps += stepsolver.steps
        return self
